
package ija.xls.notation.specific;

import ija.model.history.HistoryMove;
import ija.xls.notation.DeskCoordinate;
import ija.xls.notation.GameMove;
import ija.xls.notation.NotationReader;
import ija.xls.notation.types.GameOperation;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * Třída pro načítání tahu určeného konkrétní textovou notaci dle zadání IJA
 * @author Radek Necas, xnecas18
 */
public class IjaNotationReader implements NotationReader {

    // Soukromé konstanty pro stavy při překládání
    private final int NONE = 0;
    private final int POSCOL = 1;
    private final int POSROW = 2;
    private final int OP = 3;

    public IjaNotationReader () {       
    }

    @Override
    public GameMove translate(String notation) {
        if((notation == null) || notation.isEmpty())
            return null;
        
        String n = notation.toLowerCase();
        GameOperation op = GameOperation.NOP;
        char c;
        int hasRead = NONE;
        char col = '\0';
        int row = 0;
        String txtOut = new String();
        
        LinkedList<DeskCoordinate> coords = new LinkedList<>();
        
        // Projdu cely retezec
        for(int i = 0; i < n.length(); i++) {
            c = n.charAt(i);
            // Pokud jde o mezeru preskakuju ji
            if(Character.isWhitespace(c))
                continue;
            
            switch(hasRead) {
                // Na zacatku nebo po operandu musim nacist pismeno sloupce
                case NONE:
                case OP:
                    if(Character.isLetter(c)) {
                        col = c;
                        hasRead = POSCOL;
                    }
                    else {
                        return null;
                    }
                    break;
                    
                // Po pismenu sloupce musim nacist cislo radku
                case POSCOL:
                    if(Character.isDigit(c)) {
                        row = (char)(c - '0');
                        coords.offerLast(new DeskCoordinate(col, row));
                        hasRead = POSROW;
                    }
                    else {
                        return null;
                    }
                    break;
                    
                // Po cislu radku musi byt operand (nebo konec, ale potom cyklus uz skoncil)
                case POSROW:
                    if(c == '-') {
                        if(op != GameOperation.NOP) {
                            return null;
                        }
                        
                        op = GameOperation.MOVE;
                    }
                    else if (c == 'x') {
                        if(op == GameOperation.MOVE) {
                            return null;
                        }
                        else {
                            op = GameOperation.JUMP;
                        }
                    }
                    else {
                        return null;
                    }
                    hasRead = OP;
                    break;
            }
            
            txtOut += c;
        }
        
        // Posledni nacteny znak musel byt cislem radku
        if(hasRead == POSROW) {
            GameMove gm = new GameMove();
            gm.setOperation(op);
            gm.addPositions(coords);
            gm.setDescription(txtOut);
            return gm;
        }
        
        return null;          
    }

    @Override
    public String translateBack(GameMove gm) {
        String s = new String();
        Iterator<DeskCoordinate> it = gm.iterator();
        DeskCoordinate pos;
        while(it.hasNext()) {
            pos = it.next();
            s += pos.toString();
            if(it.hasNext()) {
                s += gm.getOperation().toString();
            }
        }
        
        return s;
    }
    
    @Override
    public HistoryMove translateRound(String line) {
        String [] splitedLine = line.split("[\\s]+");
        if(splitedLine.length != 3) {
            return null;
        }
        
        HistoryMove hm = new HistoryMove();
        int id;
        try {
            id = Integer.parseInt(splitedLine[0].substring(0, splitedLine[0].length()-1));
        } catch (NumberFormatException e) {
            System.err.println("Spatne id tahu: " + e.getMessage());
            return null;
        }
        hm.setId(id);
        
        GameMove gm = translate(splitedLine[1]);
        if(gm == null) {
            return null;
        }
        hm.addFirstMove(gm);
        
        gm = translate(splitedLine[2]);
        if(gm == null) {
            return null;
        }
        hm.addSecondMove(gm);
        
        return hm;
    }
    
    @Override
    public String translateRoundBack(HistoryMove historyMove) {
        String ret  = String.valueOf(historyMove.getId()) + ". "
                    + translateBack(historyMove.getFirstMove()) + " "
                    + translateBack(historyMove.getSecondMove());
        
        return ret;
    }
}
